// videocapture.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>

#include <C:\WMSDK\WMEncSDK9\include\wmencode.h>
#include <atlbase.h>
#include <comdef.h>
#include <conio.h>

// Define the screen capture properties.
#define WMSCRNCAP_CAPTUREWINDOW     CComBSTR("CaptureWindow")
#define WMSCRNCAP_WINDOWLEFT        CComBSTR("Left")
#define WMSCRNCAP_WINDOWTOP         CComBSTR("Top")
#define WMSCRNCAP_WINDOWRIGHT       CComBSTR("Right")
#define WMSCRNCAP_WINDOWBOTTOM      CComBSTR("Bottom")
#define WMSCRNCAP_FLASHRECT         CComBSTR("FlashRect")
#define WMSCRNCAP_ENTIRESCREEN      CComBSTR("Screen")
#define WMSCRNCAP_WINDOWTITLE       CComBSTR("WindowTitle")



#define VIDEOCODEC                    MAKEFOURCC('M','S','S','2')
#define CONTENT_TYPE_VIDEO_ONLY        16        //Profile Supports Only Video
#define CONTENT_TYPE_AUDIO_VIDEO    17        //Profile Supports both audio and Video

#define PROFILE_CONTENT_TYPE        CONTENT_TYPE_VIDEO_ONLY        //Change this to Audio_Video for Audio support

#define PROFILE_AUDIENCE_BITRATE    400000    //Target for 400 Kbps

#define VIDEOFRAMERATE                30        //15 FPS(Frames Per Second)

#define IMAGEQUALITY                100        // 0 ~ 100: The higher the number the better the quality


int _tmain(int argc, _TCHAR* argv[])
{
    // Declare variables.
    HRESULT hr = S_OK;
    IWMEncoder* pEncoder;
    IWMEncFile* pFile;

	IWMEncProfile2*        pProfile=NULL;

	IWMEncSourceGroupCollection* pSrcGrpColl=NULL;
	IWMEncSourceGroup* pSrcGrp=NULL;
	IWMEncSource* pSrc=NULL;
	IWMEncVideoSource2* pSrcVid=NULL;
	IPropertyBag* pPropertyBag=NULL;
	CComVariant varValue=NULL;

	IWMEncProfileCollection* pProColl=NULL;
    IWMEncProfile* pPro=NULL;

	IWMEncAudienceObj*    pAudience=NULL;


	CComBSTR bstrName = NULL;
	long lCount;
    int i;


    // Initialize the COM library and retrieve a pointer to an IWMEncoder interface.
    hr = CoInitialize(NULL);
    if ( SUCCEEDED( hr ) )
    {
        hr = CoCreateInstance(CLSID_WMEncoder,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_IWMEncoder,
            (void**) &pEncoder);
    }

    // Specify a file object in which to save encoded content.
    if ( SUCCEEDED( hr ) )
    {
        hr = pEncoder->get_File(&pFile);
    }
    if ( SUCCEEDED( hr ) )
    {
        hr = pFile->put_LocalFileName(CComBSTR("OutputFile.wmv"));
    }


//************************************
// Retrieve the source group collection.
if ( SUCCEEDED( hr ) )
{
    hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);
}

// Add a source group to the collection.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcGrpColl->Add(CComBSTR("SG_1"), &pSrcGrp);
}
if ( SUCCEEDED( hr ) )
{
    hr = pSrcGrp->AddSource(WMENC_VIDEO, &pSrc);
}

// Retrieve an IWMEncVideoSource2 pointer.
if ( SUCCEEDED( hr ) )
{
    hr = pSrc->QueryInterface(IID_IWMEncVideoSource2, (void**)&pSrcVid);
}

// Add a video source to the source group.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcVid->SetInput(CComBSTR("ScreenCap://ScreenCapture1"));
}

// Retrieve a pointer to the property bag.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcVid->QueryInterface(IID_IPropertyBag, (void**)&pPropertyBag);
}

// Set full screen capture.
{
    varValue = true;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );
    }
}

// Set the capture area.
{
    // nLeft, nRight, nTop, and nBottom are the dimensions to capture
    int nLeft, nRight, nTop, nBottom;

	nLeft = 0;
	nTop = 0;
	nRight = ::GetSystemMetrics(SM_CXSCREEN);
	nBottom = ::GetSystemMetrics(SM_CYSCREEN);
    // Initialize the capture area. The size must be even.
    varValue = false;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );
    }

    varValue = nLeft;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWLEFT, &varValue );
    }

    varValue = nRight;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWRIGHT, &varValue );
    }

    varValue = nTop;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWTOP, &varValue );
    }

    varValue = nBottom;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWBOTTOM, &varValue );
    }

    varValue = true;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_FLASHRECT, &varValue );
    }
}
    // Continue configuring the encoding session.

//**********************

    if (SUCCEEDED(hr))
    {
		hr = CoCreateInstance(CLSID_WMEncProfile2,NULL,CLSCTX_INPROC_SERVER,IID_IWMEncProfile2,(void**)&pProfile);
    }
    if (SUCCEEDED(hr))                        //Verify the settings immediately as they are set
    {
		hr = pProfile->put_ValidateMode(true);
        //OutputDebugString(L"Unable to Set Validate Mode");
        //return E_FAIL;
    }
    if (SUCCEEDED(hr))                        
    {
		hr = pProfile->put_ProfileName(CComBSTR("Custom Screen Capture Profile"));
//        OutputDebugString(L"Unable to Set Profile Name");
//        return E_FAIL;
    }
    if (SUCCEEDED(hr))
    {
		hr = pProfile->put_ProfileDescription(CComBSTR("A Custom Video Profile For Screen Capture"));
        //OutputDebugString(L"Unable to Set Profile Description");
       // return E_FAIL;
    }
    if (SUCCEEDED(hr))        //Content Type for our Profile - By default it is - CONTENT_TYPE_VIDEO_ONLY
    {
		hr = pProfile->put_ContentType(PROFILE_CONTENT_TYPE);
//        OutputDebugString(L"Unable to Set Content Type for Profile");
//        return E_FAIL;
    }
    if (SUCCEEDED(hr))    //Set CBR Mode - Compatible with Older Version Players
    {
		hr = pProfile->put_VBRMode(WMENC_VIDEO,0,WMENC_PVM_NONE);
        //OutputDebugString(L"Unable to Set BitRate Mode");
        //return E_FAIL;
    }
    if(SUCCEEDED(hr))
    {
		hr = pProfile->AddAudience(PROFILE_AUDIENCE_BITRATE,&pAudience);
//        OutputDebugString(L"Unable to Set Target Audience");
//        return E_FAIL;
    }

 //   do
 //   {
        long lCodecIndex=-1;
        if(SUCCEEDED(hr))
        {
			hr = pProfile->GetCodecIndexFromFourCC(WMENC_VIDEO,VIDEOCODEC,&lCodecIndex);
            //OutputDebugString(L"Unable to Get Codec Index");
            //break;
        }
        if(SUCCEEDED(hr))            //Set the Codec for the Target Audience
        {
			hr = pAudience->put_VideoCodec(0,lCodecIndex);
            //OutputDebugString(L"Unable to Set Codec");
            //break;
        }
        if(SUCCEEDED(hr))                        //Use the same as the input
        {
			hr = pAudience->put_VideoHeight(0,0);
//            OutputDebugString(L"Unable to Set Video Height");
//            break;
        }
        if(SUCCEEDED(hr))                        //Use the same width as the input
        {
			hr = pAudience->put_VideoWidth(0,0);
//            OutputDebugString(L"Unable to Set Video Width");
//            break;
        }
        if(SUCCEEDED(hr))                //Set buffer size for 5 seconds
        {
			hr = pAudience->put_VideoBufferSize(0,5000);
//            OutputDebugString(L"Unable to Set Buffer Size");
//            break;
        }
        if (SUCCEEDED(hr))    //Set the Video Frame Rate
        {
			hr = pAudience->put_VideoFPS(0,VIDEOFRAMERATE * 1000);
//            OutputDebugString(L"Unable to Set Video Frame Rate");
//            break;
        }
        if(SUCCEEDED(hr))   //Set the Best Image Sharpness possible
        {
			hr = pAudience->put_VideoImageSharpness(0,IMAGEQUALITY);
            //OutputDebugString(L"Unable to Set Video Image Sharpness");
            //break;
        }
        if(SUCCEEDED(hr))                                //Test the Profile Settings
        {
			hr = pProfile->Validate();
            //OutputDebugString(L"Unable to Validate the Profile Settings");
            //break;
        }
        if(pAudience)
        {
            pAudience->Release();
            pAudience=NULL;
        }
   //     hr = S_OK;
	//	break;

   // }while(false);

	if(SUCCEEDED(hr)) 
    {
		hr = hr=pProfile->QueryInterface(IID_IWMEncProfile,(void**)&pPro);
//            OutputDebugString(L"Unable to Query Interface For Profile");
//            return E_FAIL;
    }

	if ( SUCCEEDED( hr ))
	{
         hr = pSrcGrp->put_Profile(CComVariant(pPro));
	}

//**********************

// Choose a profile from the collection.
  //  if ( SUCCEEDED( hr ) )
  //  {
  //      hr = pEncoder->get_ProfileCollection(&pProColl);
  //  }
  //  if ( SUCCEEDED( hr ) )
  //  {
  //      hr = pProColl->get_Count(&lCount);
  //  }
  //  for (i=0; i<lCount; i++)
  //  {
  //      if ( SUCCEEDED( hr ) )
  //      {
  //          hr = pProColl->Item(i, &pPro);
  //      }
  //      if ( SUCCEEDED( hr ) )
  //      {
  //          hr = pPro->get_Name(&bstrName);
  //      }
  //      //if (_wcsicmp(bstrName,CComBSTR("Windows Media Video 8 for Local Area Network (384 Kbps)"))==0)
		//if (_wcsicmp(bstrName,CComBSTR("Windows Media Video 8 for LAN, Cable Modem, or xDSL (100 to 768 Kbps)"))==0)
  //      {
  //          // Set the profile in the source group.
  //          if ( SUCCEEDED( hr ) )
  //          {
  //              hr = pSrcGrp->put_Profile(CComVariant(pPro));
  //          }
  //          break;
  //      }
  //  }

// Start the encoding process.
    if ( SUCCEEDED( hr ) )
    {
        hr = pEncoder->PrepareToEncode(VARIANT_TRUE);
    }
    if ( SUCCEEDED( hr ) )
    {
        hr = pEncoder->Start();
        // Keep the console window open.
        printf("When encoding stops, press a key to close the console window.");

        // Stop the encoding process.
        if ( SUCCEEDED( hr ) )
        {
            // Wait for a key press.
            while(!_kbhit())
               _asm nop;

            hr = pEncoder->Stop();
        }
    }


//************************************


    // Release pointers.
     if ( pProColl )
    {
        pProColl->Release();
        pProColl = NULL;
    }
    if ( pPro )
    {
        pPro->Release();
        pPro = NULL;
    }


   if ( pSrcGrpColl )
    {
        pSrcGrpColl->Release();
        pSrcGrpColl = NULL;
    }
    if ( pSrcGrp )
    {
        pSrcGrp->Release();
        pSrcGrp = NULL;
    }
    if ( pSrcVid )
    {
        pSrcVid->Release();
        pSrcVid = NULL;
    }
    if ( pSrc )
    {
        pSrc->Release();
        pSrc = NULL;
    }
    if ( pPropertyBag )
    {
        pPropertyBag->Release();
        pPropertyBag = NULL;
    }


    if ( pFile )
    {
        pFile->Release();
        pFile = NULL;
    }
    if ( pEncoder )
    {
        pEncoder->Release();
        pEncoder = NULL;
    }

	    if(pProfile)
    {
        pProfile->Release();
        pProfile =NULL;
    }

}

